﻿// This file is part of SNMP#NET.
// 
// SNMP#NET is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// SNMP#NET is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with SNMP#NET.  If not, see <http://www.gnu.org/licenses/>.
// 

namespace SnmpSharpNet
{
	/// <summary>
	/// Privacy protocol interface.
	/// </summary>
	/// <remarks>
	/// Defines encryption and decryption methods for all privacy protocols allowing for any of the
	/// available protocols to be cast as the interface and called to perform privacy operations on packets.
	/// </remarks>
	public interface IPrivacyProtocol
	{
		/// <summary>
		/// Encrypt <see cref="ScopedPdu"/> data BER encoded in a byte array.
		/// </summary>
		/// <param name="unencryptedData">BER encoded <see cref="ScopedPdu"/> byte array that needs to be encrypted</param>
		/// <param name="offset">Offset within the BER encoded byte array to start encryption operation from.</param>
		/// <param name="length">Length of data to encrypt</param>
		/// <param name="encryptionKey">Encryption key</param>
		/// <param name="engineBoots">Authoritative engine boots value. Retrieved as part of SNMP v3 discovery process.</param>
		/// <param name="engineTime">Authoritative engine time value. Retrieved as part of SNMP v3 discovery process.</param>
		/// <param name="privacyParameters">Byte array that will receive privacy parameters information that is the result of the
		/// encryption procedure.</param>
		/// <param name="authDigest">Authentication digest class reference. Only needed for TripleDES privacy protocol. Can be null for all other
		/// privacy protocols.</param>
		/// <returns>Byte array containing encrypted <see cref="ScopedPdu"/> BER encoded data</returns>
		byte[] Encrypt(byte[] unencryptedData, int offset, int length, byte[] encryptionKey, int engineBoots, int engineTime, out byte[] privacyParameters, IAuthenticationDigest authDigest);
		/// <summary>
		/// Decrypt <see cref="ScopedPdu"/> BER encoded byte array.
		/// </summary>
		/// <param name="cryptedData">Encrypted data byte array</param>
		/// <param name="offset">Offset within the buffer to start decryption process from</param>
		/// <param name="length">Length of data to decrypt</param>
		/// <param name="key">Decryption key</param>
		/// <param name="engineBoots">Authoritative engine boots value. Retrieved as part of SNMP v3 discovery procedure</param>
		/// <param name="engineTime">Authoritative engine time value. Retrieved as part of SNMP v3 discovery procedure</param>
		/// <param name="privacyParameters">Privacy parameters parsed from the incoming packet.</param>
		/// <returns>Byte array containing decrypted <see cref="ScopedPdu"/> in BER encoded format.</returns>
		byte[] Decrypt(byte[] cryptedData, int offset, int length, byte[] key, int engineBoots, int engineTime, byte[] privacyParameters);
		/// <summary>
		/// Get minimum acceptable encryption/decryption key length for the protocol.
		/// </summary>
		int MinimumKeyLength
		{
			get;
		}
		/// <summary>
		/// Get maximum acceptable encryption/decryption key length for the protocol.
		/// </summary>
		int MaximumKeyLength
		{
			get;
		}
		/// <summary>SNMP version 3 packet privacy parameters field size</summary>
		/// <remarks>
		/// Get length of the privacy parameters byte array that is generated by the encryption method and used by the
		/// decryption method.
		/// </remarks>
		int PrivacyParametersLength
		{
			get;
		}
		/// <summary>
		/// Privacy protocol name
		/// </summary>
		string Name
		{
			get;
		}
		/// <summary>
		/// Calculates and returns length of the buffer that is the result of the encryption method.
		/// </summary>
		/// <param name="scopedPduLength">Length of the buffer that is needs to be encrypted.</param>
		/// <returns>Length of the encrypted byte array after the call to Encrypt method.</returns>
		int GetEncryptedLength(int scopedPduLength);
		/// <summary>Extend short encryption key</summary>
		/// <remarks>
		/// Some privacy protocols require generated key to be extended to match the minimum key size
		/// required by the encryption alghoritm. Where required, this method should be called by the
		/// inheriting class as part of PasswordToKey() method call without the need for user to call it.
		/// </remarks>
		/// <param name="shortKey">Key that needs to be extended</param>
		/// <param name="password">Privacy password as configured on the SNMP agent.</param>
		/// <param name="engineID">Authoritative engine id. Value is retrieved as part of SNMP v3 discovery procedure</param>
		/// <param name="authProtocol">Authentication protocol class instance cast as <see cref="IAuthenticationDigest"/></param>
		/// <returns>Extended key value</returns>
		byte[] ExtendShortKey(byte[] shortKey, byte[] password, byte[] engineID, IAuthenticationDigest authProtocol);

		/// <summary>
		/// Returns true if derived class supports key extension, otherwise false.
		/// </summary>
		bool CanExtendShortKey
		{
			get;
		}
		/// <summary>
		/// Convert privacy password into encryption key using packet authentication hash.
		/// </summary>
		/// <param name="secret">Privacy user secret</param>
		/// <param name="engineId">Authoritative engine id of the snmp agent</param>
		/// <param name="authProtocol">Authentication protocol</param>
		/// <returns>Encryption key</returns>
		/// <exception cref="SnmpPrivacyException">Thrown when key size is shorter then MinimumKeyLength</exception>
		byte[] PasswordToKey(byte[] secret, byte[] engineId, IAuthenticationDigest authProtocol);
	}
}
